home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / hydra.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  18KB  |  718 lines

  1. /***************************************************************************
  2.  
  3.     vidhrdw/hydra.c
  4.  
  5.     Functions to emulate the video hardware of the machine.
  6.  
  7. ****************************************************************************
  8.  
  9.     Playfield encoding
  10.     ------------------
  11.         1 16-bit word is used
  12.  
  13.         Word 1:
  14.             Bit  15    = horizontal flip
  15.             Bits 11-14 = palette
  16.             Bits  0-12 = image index
  17.  
  18.  
  19.     Motion Object encoding
  20.     ----------------------
  21.         4 16-bit words are used
  22.  
  23.         Word 1:
  24.             Bit  15    = horizontal flip
  25.             Bits  0-14 = image index
  26.  
  27.         Word 2:
  28.             Bits  7-15 = Y position
  29.             Bits  0-3  = height in tiles
  30.  
  31.         Word 3:
  32.             Bits  3-10 = link to the next image to display
  33.  
  34.         Word 4:
  35.             Bits  6-14 = X position
  36.             Bit   4    = use current X position + 16 for next sprite
  37.             Bits  0-3  = palette
  38.  
  39.  
  40.     Alpha layer encoding
  41.     --------------------
  42.         1 16-bit word is used
  43.  
  44.         Word 1:
  45.             Bit  15    = horizontal flip
  46.             Bit  12-14 = palette
  47.             Bits  0-11 = image index
  48.  
  49. ***************************************************************************/
  50.  
  51. #include "driver.h"
  52. #include "machine/atarigen.h"
  53. #include "vidhrdw/generic.h"
  54.  
  55. /* Note: if this is set to 1, it must also be set in the driver */
  56. #define HIGH_RES 0
  57.  
  58. #define XCHARS 42
  59. #define YCHARS 30
  60.  
  61. #define XDIM (XCHARS*(8 << HIGH_RES))
  62. #define YDIM (YCHARS*8)
  63.  
  64.  
  65. #define DEBUG_VIDEO 0
  66.  
  67.  
  68.  
  69. /*************************************
  70.  *
  71.  *    Globals
  72.  *
  73.  *************************************/
  74.  
  75. struct rectangle hydra_mo_area;
  76. UINT32 hydra_mo_priority_offset;
  77. INT32 hydra_pf_xoffset;
  78.  
  79.  
  80.  
  81. /*************************************
  82.  *
  83.  *    Structures
  84.  *
  85.  *************************************/
  86.  
  87. struct mo_params
  88. {
  89.     int xhold;
  90.     struct osd_bitmap *bitmap;
  91. };
  92.  
  93.  
  94. struct mo_sort_entry
  95. {
  96.     struct mo_sort_entry *next;
  97.     int entry;
  98. };
  99.  
  100.  
  101.  
  102. /*************************************
  103.  *
  104.  *    Statics
  105.  *
  106.  *************************************/
  107.  
  108. static struct atarigen_pf_state pf_state;
  109. static UINT16 current_control;
  110.  
  111.  
  112.  
  113. /*************************************
  114.  *
  115.  *    Prototypes
  116.  *
  117.  *************************************/
  118.  
  119. static const UINT8 *update_palette(void);
  120.  
  121. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param);
  122. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param);
  123.  
  124. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  125. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  126.  
  127. #if DEBUG_VIDEO
  128. static int debug(void);
  129. #endif
  130.  
  131.  
  132.  
  133. /*************************************
  134.  *
  135.  *    Video system start
  136.  *
  137.  *************************************/
  138.  
  139. int hydra_vh_start(void)
  140. {
  141.     static struct atarigen_pf_desc pf_desc =
  142.     {
  143.         8 << HIGH_RES, 8,    /* width/height of each tile */
  144.         64, 64                /* number of tiles in each direction */
  145.     };
  146.  
  147.  
  148.     /* reset statics */
  149.     memset(&pf_state, 0, sizeof(pf_state));
  150.     current_control = 0;
  151.  
  152.     /* add the top bit to the playfield graphics */
  153.     if (Machine->gfx[0])
  154.     {
  155.         const UINT8 *src = &memory_region(REGION_GFX1)[0x80000];
  156.         unsigned int *pen_usage = Machine->gfx[0]->pen_usage;
  157.         int n, h, w;
  158.         UINT8 *dst = Machine->gfx[0]->gfxdata;
  159.  
  160.         for (n = 0; n < Machine->gfx[0]->total_elements; n ++)
  161.         {
  162.             unsigned int usage = 0;
  163.  
  164.             for (h = 0; h < 8; h++)
  165.             {
  166.                 UINT8 bits = *src++;
  167.  
  168.                 for (w = 0; w < 8; w++, dst += (1 << HIGH_RES), bits <<= 1)
  169.                 {
  170.                     dst[0] = (dst[0] & 0x0f) | ((bits >> 3) & 0x10);
  171.                     if (HIGH_RES)
  172.                         dst[1] = (dst[1] & 0x0f) | ((bits >> 3) & 0x10);
  173.                     usage |= 1 << dst[0];
  174.                 }
  175.             }
  176.  
  177.             /* update the tile's pen usage */
  178.             if (pen_usage)
  179.                 *pen_usage++ = usage;
  180.         }
  181.     }
  182.  
  183.     /* decode the motion objects */
  184.     if (atarigen_rle_init(REGION_GFX3, 0x200))
  185.         return 1;
  186.  
  187.     /* initialize the playfield */
  188.     if (atarigen_pf_init(&pf_desc))
  189.     {
  190.         atarigen_rle_free();
  191.         return 1;
  192.     }
  193.  
  194.     return 0;
  195. }
  196.  
  197.  
  198.  
  199. /*************************************
  200.  *
  201.  *    Video system shutdown
  202.  *
  203.  *************************************/
  204.  
  205. void hydra_vh_stop(void)
  206. {
  207.     atarigen_rle_free();
  208.     atarigen_pf_free();
  209. }
  210.  
  211.  
  212.  
  213. /*************************************
  214.  *
  215.  *    Playfield RAM write handler
  216.  *
  217.  *************************************/
  218.  
  219. WRITE_HANDLER( hydra_playfieldram_w )
  220. {
  221.     int oldword = READ_WORD(&atarigen_playfieldram[offset]);
  222.     int newword = COMBINE_WORD(oldword, data);
  223.  
  224.     if (oldword != newword)
  225.     {
  226.         WRITE_WORD(&atarigen_playfieldram[offset], newword);
  227.         atarigen_pf_dirty[(offset / 2) & 0xfff] = 0xff;
  228.     }
  229. }
  230.  
  231.  
  232.  
  233. /*************************************
  234.  *
  235.  *    Periodic scanline updater
  236.  *
  237.  *************************************/
  238.  
  239. WRITE_HANDLER( hydra_mo_control_w )
  240. {
  241.     logerror("MOCONT = %d (scan = %d)\n", data, cpu_getscanline());
  242.  
  243.     /* set the control value */
  244.     current_control = data;
  245. }
  246.  
  247.  
  248. void hydra_scanline_update(int scanline)
  249. {
  250.     UINT16 *base = (UINT16 *)&atarigen_alpharam[((scanline / 8) * 64 + 47) * 2];
  251.     int i;
  252.  
  253.     if (scanline == 0) logerror("-------\n");
  254.  
  255.     /* keep in range */
  256.     if ((UINT8 *)base >= &atarigen_alpharam[atarigen_alpharam_size])
  257.         return;
  258.  
  259.     /* update the current parameters */
  260.     for (i = 0; i < 8; i++)
  261.     {
  262.         int word;
  263.  
  264.         word = base[i * 2 + 1];
  265.         if (word & 0x8000)
  266.             pf_state.hscroll = (((word >> 6) + hydra_pf_xoffset) & 0x1ff) << HIGH_RES;
  267.  
  268.         word = base[i * 2 + 2];
  269.         if (word & 0x8000)
  270.         {
  271.             /* a new vscroll latches the offset into a counter; we must adjust for this */
  272.             int offset = scanline + i;
  273.             if (offset >= 256)
  274.                 offset -= 256;
  275.             pf_state.vscroll = ((word >> 6) - offset) & 0x1ff;
  276.  
  277.             pf_state.param[0] = word & 7;
  278.         }
  279.  
  280.         /* update the playfield with the new parameters */
  281.         atarigen_pf_update(&pf_state, scanline + i);
  282.     }
  283. }
  284.  
  285.  
  286.  
  287. /*************************************
  288.  *
  289.  *    Main refresh
  290.  *
  291.  *************************************/
  292.  
  293. void hydra_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  294. {
  295.     /*     a note about this: I don't see how to compute the MO ROM checksums, so these
  296.         are just the values Pit Fighter is expecting. Hydra never checks. */
  297.     static UINT16 mo_checksum[16] =
  298.     {
  299.         0xc289, 0x3103, 0x2b8d, 0xe048, 0xc12e, 0x0ede, 0x2cd7, 0x7dc8,
  300.         0x58fc, 0xb877, 0x9449, 0x59d4, 0x8b63, 0x241b, 0xa3de, 0x4724
  301.     };
  302.  
  303.     struct mo_sort_entry sort_entry[256];
  304.     struct mo_sort_entry *list_head[256];
  305.     struct mo_sort_entry *current;
  306.  
  307.     struct mo_params modata;
  308.     const struct GfxElement *gfx;
  309.     int x, y, offs;
  310.  
  311. #if DEBUG_VIDEO
  312.     int xorval = debug();
  313. #endif
  314.  
  315.     /* special case: checksum the sprite ROMs */
  316.     if (READ_WORD(&atarigen_spriteram[0]) == 0x000f)
  317.     {
  318.         for (x = 1; x < 5; x++)
  319.             if (READ_WORD(&atarigen_spriteram[x * 2]) != 0)
  320.                 break;
  321.         if (x == 5)
  322.         {
  323.             logerror("Wrote checksums\n");
  324.             for (x = 0; x < 16; x++)
  325.                 WRITE_WORD(&atarigen_spriteram[x * 2], mo_checksum[x]);
  326.         }
  327.     }
  328.  
  329.     /* update the palette, and mark things dirty */
  330.     if (update_palette())
  331.         memset(atarigen_pf_dirty, 0xff, atarigen_playfieldram_size / 2);
  332.  
  333.     /* draw the playfield */
  334.     memset(atarigen_pf_visit, 0, 64*64);
  335.     atarigen_pf_process(pf_render_callback, bitmap, &Machine->drv->visible_area);
  336.  
  337.     /* draw the motion objects */
  338.     modata.xhold = 1000;
  339.     modata.bitmap = bitmap;
  340.  
  341.     /* sort the motion objects into their proper priorities */
  342.     memset(list_head, 0, sizeof(list_head));
  343.     for (x = 0; x < 256; x++)
  344.     {
  345.         int priority = READ_WORD(&atarigen_spriteram[x * 16 + hydra_mo_priority_offset]) & 0xff;
  346.         sort_entry[x].entry = x;
  347.         sort_entry[x].next = list_head[priority];
  348.         list_head[priority] = &sort_entry[x];
  349.     }
  350.  
  351.     /* now loop back and process */
  352.     for (x = 1; x < 256; x++)
  353.         for (current = list_head[x]; current; current = current->next)
  354.             mo_render_callback((const UINT16 *)&atarigen_spriteram[current->entry * 16], &hydra_mo_area, &modata);
  355.  
  356.     /* draw the alphanumerics */
  357.     gfx = Machine->gfx[1];
  358.     for (y = 0; y < YCHARS; y++)
  359.         for (x = 0, offs = y * 64; x < XCHARS; x++, offs++)
  360.         {
  361.             int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  362.             int code = data & 0xfff;
  363.             int color = (data >> 12) & 15;
  364.             int opaque = data & 0x8000;
  365.             drawgfx(bitmap, gfx, code, color, 0, 0, (8 << HIGH_RES) * x, 8 * y, 0, opaque ? TRANSPARENCY_NONE : TRANSPARENCY_PEN, 0);
  366.         }
  367.  
  368.     /* update onscreen messages */
  369.     atarigen_update_messages();
  370. }
  371.  
  372.  
  373.  
  374. /*************************************
  375.  *
  376.  *    Palette management
  377.  *
  378.  *************************************/
  379.  
  380. static const UINT8 *update_palette(void)
  381. {
  382.     UINT16 mo_map[16+4], al_map[16];
  383.     UINT32 pf_map[8];
  384.     const unsigned int *usage;
  385.     int i, j, x, y, offs;
  386.  
  387.     /* reset color tracking */
  388.     memset(mo_map, 0, sizeof(mo_map));
  389.     memset(pf_map, 0, sizeof(pf_map));
  390.     memset(al_map, 0, sizeof(al_map));
  391.     palette_init_used_colors();
  392.  
  393.     /* update color usage for the playfield */
  394.     atarigen_pf_process(pf_color_callback, pf_map, &Machine->drv->visible_area);
  395.  
  396.     /* update color usage for the mo's */
  397.     for (j = 0; j < 256; j++)
  398.     {
  399.         int priority = READ_WORD(&atarigen_spriteram[j * 16 + hydra_mo_priority_offset]) & 0xff;
  400.         if (priority != 0)
  401.             mo_color_callback((const UINT16 *)&atarigen_spriteram[j * 16], &Machine->drv->visible_area, mo_map);
  402.     }
  403.  
  404.     /* update color usage for the alphanumerics */
  405.     usage = Machine->gfx[1]->pen_usage;
  406.     for (y = 0; y < YCHARS; y++)
  407.         for (x = 0, offs = y * 64; x < XCHARS; x++, offs++)
  408.         {
  409.             int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  410.             int code = data & 0xfff;
  411.             int color = (data >> 12) & 15;
  412.             al_map[color] |= usage[code];
  413.         }
  414.  
  415.     /* rebuild the playfield palette */
  416.     for (i = 0; i < 8; i++)
  417.     {
  418.         UINT32 used = pf_map[i];
  419.         if (used)
  420.             for (j = 0; j < 32; j++)
  421.                 if (used & (1 << j))
  422.                     palette_used_colors[0x300 + i * 32 + j] = PALETTE_COLOR_USED;
  423.     }
  424.  
  425.     /* rebuild the motion object palette */
  426.     for (i = 0; i < 16; i++)
  427.     {
  428.         UINT16 used = mo_map[i];
  429.         if (used)
  430.         {
  431.             for (j = 0; j < 16; j++)
  432.                 if (used & (1 << j))
  433.                     palette_used_colors[0x200 + i * 16 + j] = PALETTE_COLOR_USED;
  434.         }
  435.     }
  436.  
  437.     /* rebuild the alphanumerics palette */
  438.     for (i = 0; i < 16; i++)
  439.     {
  440.         UINT16 used = al_map[i];
  441.         if (used)
  442.         {
  443.             if (i < 8)
  444.                 palette_used_colors[0x100 + i * 16 + 0] = PALETTE_COLOR_TRANSPARENT;
  445.             else if (used & 0x0001)
  446.                 palette_used_colors[0x100 + i * 16 + 0] = PALETTE_COLOR_USED;
  447.             for (j = 1; j < 16; j++)
  448.                 if (used & (1 << j))
  449.                     palette_used_colors[0x100 + i * 16 + j] = PALETTE_COLOR_USED;
  450.         }
  451.     }
  452.  
  453.     /* recalc */
  454.     return palette_recalc();
  455. }
  456.  
  457.  
  458.  
  459. /*************************************
  460.  *
  461.  *    Playfield palette
  462.  *
  463.  *************************************/
  464.  
  465. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  466. {
  467.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  468.     UINT32 *colormap = (UINT32 *)param;
  469.     int bankbase = state->param[0] * 0x1000;
  470.     int x, y;
  471.  
  472.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  473.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  474.         {
  475.             int offs = y * 64 + x;
  476.             int data = READ_WORD(&atarigen_playfieldram[offs * 2]);
  477.             int code = bankbase + (data & 0x0fff);
  478.             int color = (data >> 12) & 7;
  479.             colormap[color] |= usage[code];
  480.  
  481.             /* also mark unvisited tiles dirty */
  482.             if (!atarigen_pf_visit[offs]) atarigen_pf_dirty[offs] = 0xff;
  483.         }
  484. }
  485.  
  486.  
  487.  
  488. /*************************************
  489.  *
  490.  *    Playfield rendering
  491.  *
  492.  *************************************/
  493.  
  494. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  495. {
  496.     const struct GfxElement *gfx = Machine->gfx[0];
  497.     int bankbase = state->param[0] * 0x1000;
  498.     struct osd_bitmap *bitmap = param;
  499.     int x, y;
  500.  
  501.     /* first update any tiles whose color is out of date */
  502.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  503.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  504.         {
  505.             int offs = y * 64 + x;
  506.             int data = READ_WORD(&atarigen_playfieldram[offs * 2]);
  507.             int color = (data >> 12) & 7;
  508.  
  509.             if (atarigen_pf_dirty[offs] != state->param[0])
  510.             {
  511.                 int code = bankbase + (data & 0x0fff);
  512.                 int hflip = data & 0x8000;
  513.  
  514.                 drawgfx(atarigen_pf_bitmap, gfx, code, color, hflip, 0, (8 << HIGH_RES) * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  515.                 atarigen_pf_dirty[offs] = state->param[0];
  516.             }
  517.  
  518.             /* track the tiles we've visited */
  519.             atarigen_pf_visit[offs] = 1;
  520.         }
  521.  
  522.     /* then blast the result */
  523.     x = -state->hscroll;
  524.     y = -state->vscroll;
  525.     copyscrollbitmap(bitmap, atarigen_pf_bitmap, 1, &x, 1, &y, clip, TRANSPARENCY_NONE, 0);
  526. }
  527.  
  528.  
  529.  
  530. /*************************************
  531.  *
  532.  *    Motion object palette
  533.  *
  534.  *************************************/
  535.  
  536. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  537. {
  538.     UINT16 *colormap = param;
  539.  
  540.     int scale = data[4];
  541.     int code = data[0] & 0x7fff;
  542.     if (scale > 0x0000 && code < atarigen_rle_count)
  543.     {
  544.         const struct atarigen_rle_descriptor *rle = &atarigen_rle_info[code];
  545.         int colorentry = (data[1] & 0xff) >> 4;
  546.         int colorshift = (data[1] & 0x0f);
  547.         int usage = rle->pen_usage;
  548.         int bpp = rle->bpp;
  549.  
  550.         if (bpp == 4)
  551.         {
  552.             colormap[colorentry + 0] |= usage << colorshift;
  553.             if (colorshift)
  554.                 colormap[colorentry + 1] |= usage >> (16 - colorshift);
  555.         }
  556.         else if (bpp == 5)
  557.         {
  558.             colormap[colorentry + 0] |= usage << colorshift;
  559.             colormap[colorentry + 1] |= usage >> (16 - colorshift);
  560.             if (colorshift)
  561.                 colormap[colorentry + 2] |= usage >> (32 - colorshift);
  562.         }
  563.         else
  564.         {
  565.             colormap[colorentry + 0] |= usage << colorshift;
  566.             colormap[colorentry + 1] |= usage >> (16 - colorshift);
  567.             if (colorshift)
  568.                 colormap[colorentry + 2] |= usage >> (32 - colorshift);
  569.  
  570.             usage = rle->pen_usage_hi;
  571.             colormap[colorentry + 2] |= usage << colorshift;
  572.             colormap[colorentry + 3] |= usage >> (16 - colorshift);
  573.             if (colorshift)
  574.                 colormap[colorentry + 4] |= usage >> (32 - colorshift);
  575.         }
  576.     }
  577. }
  578.  
  579.  
  580.  
  581. /*************************************
  582.  *
  583.  *    Motion object rendering
  584.  *
  585.  *************************************/
  586.  
  587. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  588. {
  589.     int scale = data[4];
  590.     int code = data[0] & 0x7fff;
  591.     if (scale > 0x0000 && code < atarigen_rle_count)
  592.     {
  593.         const struct mo_params *modata = param;
  594.         struct osd_bitmap *bitmap = modata->bitmap;
  595.         int hflip = data[0] & 0x8000;
  596.         int color = data[1] & 0xff;
  597.         int x = ((INT16)data[2] >> 6);
  598.         int y = ((INT16)data[3] >> 6);
  599.  
  600.         atarigen_rle_render(bitmap, &atarigen_rle_info[code], color, hflip, 0, (x << HIGH_RES) + clip->min_x, y, scale << HIGH_RES, scale, clip);
  601.     }
  602. }
  603.  
  604.  
  605.  
  606. /*************************************
  607.  *
  608.  *    Debugging
  609.  *
  610.  *************************************/
  611.  
  612. #if DEBUG_VIDEO
  613.  
  614. static void mo_print_callback(struct osd_bitmap *bitmap, struct rectangle *clip, UINT16 *data, void *param)
  615. {
  616.     int code = (data[0] & 0x7fff);
  617.     int vsize = (data[1] & 15) + 1;
  618.     int xpos = (data[3] >> 7);
  619.     int ypos = (data[1] >> 7);
  620.     int color = data[3] & 15;
  621.     int hflip = data[0] & 0x8000;
  622.  
  623.     FILE *f = (FILE *)param;
  624.     fprintf(f, "P=%04X X=%03X Y=%03X SIZE=%X COL=%X FLIP=%X  -- DATA=%04X %04X %04X %04X\n",
  625.             code, xpos, ypos, vsize, color, hflip >> 15, data[0], data[1], data[2], data[3]);
  626. }
  627.  
  628. static int debug(void)
  629. {
  630.     int hidebank = -1;
  631.  
  632.     if (keyboard_pressed(KEYCODE_Q)) hidebank = 0;
  633.     if (keyboard_pressed(KEYCODE_W)) hidebank = 1;
  634.     if (keyboard_pressed(KEYCODE_E)) hidebank = 2;
  635.     if (keyboard_pressed(KEYCODE_R)) hidebank = 3;
  636.     if (keyboard_pressed(KEYCODE_T)) hidebank = 4;
  637.     if (keyboard_pressed(KEYCODE_Y)) hidebank = 5;
  638.     if (keyboard_pressed(KEYCODE_U)) hidebank = 6;
  639.     if (keyboard_pressed(KEYCODE_I)) hidebank = 7;
  640.  
  641.     if (keyboard_pressed(KEYCODE_A)) hidebank = 8;
  642.     if (keyboard_pressed(KEYCODE_S)) hidebank = 9;
  643.     if (keyboard_pressed(KEYCODE_D)) hidebank = 10;
  644.     if (keyboard_pressed(KEYCODE_F)) hidebank = 11;
  645.     if (keyboard_pressed(KEYCODE_G)) hidebank = 12;
  646.     if (keyboard_pressed(KEYCODE_H)) hidebank = 13;
  647.     if (keyboard_pressed(KEYCODE_J)) hidebank = 14;
  648.     if (keyboard_pressed(KEYCODE_K)) hidebank = 15;
  649.  
  650.     if (keyboard_pressed(KEYCODE_9))
  651.     {
  652.         static int count;
  653.         char name[50];
  654.         FILE *f;
  655.         int i;
  656.  
  657.         while (keyboard_pressed(KEYCODE_9)) { }
  658.  
  659.         sprintf(name, "Dump %d", ++count);
  660.         f = fopen(name, "wt");
  661.  
  662.         fprintf(f, "\n\nPalette RAM:\n");
  663.  
  664.         for (i = 0x000; i < 0x800; i++)
  665.         {
  666.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  667.             if ((i & 15) == 15) fprintf(f, "\n");
  668.             if ((i & 255) == 255) fprintf(f, "\n");
  669.         }
  670.  
  671.         fprintf(f, "\n\nMotion Objects (drawn)\n");
  672. /*        atarigen_mo_process(mo_print_callback, f);*/
  673.  
  674.         fprintf(f, "\n\nMotion Objects (control = %d)\n", current_control);
  675.         for (i = 0; i < 0x100; i++)
  676.         {
  677.             fprintf(f, "   Object %03X:  P=%04X  ?=%04X  X=%04X  Y=%04X  S=%04X  ?=%04X  L=%04X  ?=%04X\n",
  678.                     i,
  679.                     READ_WORD(&atarigen_spriteram[i*16+0]),
  680.                     READ_WORD(&atarigen_spriteram[i*16+2]),
  681.                     READ_WORD(&atarigen_spriteram[i*16+4]),
  682.                     READ_WORD(&atarigen_spriteram[i*16+6]),
  683.                     READ_WORD(&atarigen_spriteram[i*16+8]),
  684.                     READ_WORD(&atarigen_spriteram[i*16+10]),
  685.                     READ_WORD(&atarigen_spriteram[i*16+12]),
  686.                     READ_WORD(&atarigen_spriteram[i*16+14])
  687.             );
  688.         }
  689.  
  690.         fprintf(f, "\n\nPlayfield dump\n");
  691.         for (i = 0; i < atarigen_playfieldram_size / 2; i++)
  692.         {
  693.             fprintf(f, "%04X ", READ_WORD(&atarigen_playfieldram[i*2]));
  694.             if ((i & 63) == 63) fprintf(f, "\n");
  695.         }
  696.  
  697.         fprintf(f, "\n\nAlpha dump\n");
  698.         for (i = 0; i < atarigen_alpharam_size / 2; i++)
  699.         {
  700.             fprintf(f, "%04X ", READ_WORD(&atarigen_alpharam[i*2]));
  701.             if ((i & 63) == 63) fprintf(f, "\n");
  702.         }
  703.  
  704.         fprintf(f, "\n\nMemory dump");
  705.         for (i = 0xff0000; i < 0xffffff; i += 2)
  706.         {
  707.             if ((i & 31) == 0) fprintf(f, "\n%06X: ", i);
  708.             fprintf(f, "%04X ", READ_WORD(&atarigen_spriteram[i - 0xff0000]));
  709.         }
  710.  
  711.         fclose(f);
  712.     }
  713.  
  714.     return hidebank;
  715. }
  716.  
  717. #endif
  718.